package de.koller.oceanFramework.math;

public class RVec2 {
	public float x, y;
	
	public RVec2() {
		this.clear();
	}
	
	public RVec2( float x, float y ) {
		this.set( x, y );
	}
	
	public RVec2( RVec2 o ) {
		this.set( o );
	}
	
	public float getDirection() {
		return(float)Math.atan2( y, x );
	}
	
	public RVec2 setLength( float l ) {
		setTo( getDirection(), l );
		return this; 
	}
	
	public RVec2 setDirection( float d ) {
		return setTo( d, getLength() );
	}
	
	public RVec2 setTo( float direction, float length ) {
		this.x = (float)Math.cos( direction ) * length;
		this.y = (float)Math.sin( direction ) * length;
		return this;
	}
	
	public final RVec2 set( RVec2 o ) {
		this.x = o.x;
		this.y = o.y;
		return this;
	}
	
	public final RVec2 set( float x, float y ) {
		this.x = x;
		this.y = y;
		return this;
	}
	
	public final RVec2 clear() {
		this.x = 0;
		this.y = 0;
		return this;
	}
	
	public final RVec2 add( float x, float y ) {
		this.x += x;
		this.y += y;
		return this;
	}
	
	public final RVec2 add( RVec2 o ) {
		return add( o.x, o.y );
	}
	
	public final RVec2 sub( RVec2 o ) {
		this.x -= o.x;
		this.y -= o.y;
		return this;
	}
	
	public final RVec2 mult( float s ) {
		this.x *= s;
		this.y *= s;
		return this;
	}
	
	public static RVec2 difference( RVec2 a, RVec2 b ) {
		return a.newInstace().sub( b );
	}
	
	public final RVec2 negate() {
		this.x = -this.x;
		this.y = -this.y;
		return this;
	}
	
	public final RVec2 newInstace() {
		return new RVec2( this );
	}
	
	@Override
	public String toString() {
		return "( " + x + ", " + y + " )";
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + Float.floatToIntBits(x);
		result = prime * result + Float.floatToIntBits(y);
		return result;
	}
	
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		RVec2 other = (RVec2)obj;
		if (Float.floatToIntBits(x) != Float.floatToIntBits(other.x))
			return false;
		if (Float.floatToIntBits(y) != Float.floatToIntBits(other.y))
			return false;
		return true;
	}
	
	public static float dot( RVec2 a, RVec2 b ) {
		return a.x * b.x + a.y * b.y;
	}
	
	public final float getLength() {
        return (float)Math.sqrt( this.getLengthSquared() );
    }

    public final float getLengthSquared() {
        return x * x + y * y;
    }
	
	public final RVec2 normalize() {
		float length = getLengthSquared();
        if( length != 1f && length != 0f ) {
            length = 1f / (float)Math.sqrt( length );
            return this.mult( length );
        } 
		return this;
	}
	
	public static float getAngle( RVec2 a, RVec2 b ) {
        float dotProduct = dot( a, b );
        float angle = (float)Math.acos( dotProduct );
        return angle;
    }

}